package com.qingge.springboot.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qingge.springboot.common.Result;
import com.qingge.springboot.controller.dto.UserDTO;
import com.qingge.springboot.entity.*;
import com.qingge.springboot.entity.Class;
import com.qingge.springboot.entity.vo.FileVo;
import com.qingge.springboot.entity.vo.TeacherCourseVo;
import com.qingge.springboot.service.*;
import com.qingge.springboot.utils.TokenUtils;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author: Mr.Wu
 * @create: 2022-12-13 09:55
 **/
@RestController
@RequestMapping("/teacher")
public class TeacherController {

    @Autowired
    private ITeacherService teacherService;

    @Autowired
    private CourseTeacherService courseTeacherService;

    @Resource
    private CourseTeacherFileService fileService;

    @Resource
    private StudentService studentService;

    @Resource
    private StudentWorkService workService;

    @Resource
    private ISchoolClassService schoolClassService;

    @GetMapping("/all")
    @ApiOperation("查询所有老师信息")
    public Result getTeacher(@RequestParam(name = "teacherName", required = false) String teacherName, @RequestParam(name = "pageSize") Integer pageSize, @RequestParam(name = "pageNum") Integer pageNum) {
        //查询所有老师信息
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.hasLength(teacherName), Teacher::getTeacherName, teacherName);
        Page<Teacher> teacherPage = teacherService.getBaseMapper().selectPage(new Page<>(pageNum, pageSize), queryWrapper);
        return Result.success(teacherPage);
    }

    @GetMapping("/course/{teacherId}")
    @ApiOperation("查询老师的授课情况")
    public Result getTeacherCourse(@PathVariable("teacherId") Integer teacherId) {
        //通过老师id查询授课
        List<TeacherCourseVo> vos = teacherService.selectCourse(teacherId);
        return Result.success(vos);
    }

    @PostMapping("/updateOrSave")
    public Result updateOrSave(@RequestBody Map<String, Object> map) {
        try {
            HashSet<Integer> set = new HashSet<Integer>();
            Object course = map.get("Course");
            Object teacherId = map.get("teacherId");
            Integer teacher = Integer.valueOf(teacherId.toString());
            if (course != null) {
                for (Object obj : (List<?>) course) {
                    set.add(Integer.valueOf(obj.toString()));
                }
            } else {
                //清空该教师的所有课程
                LambdaQueryWrapper<CourseTeacher> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(CourseTeacher::getTeacherId, teacher);
                courseTeacherService.remove(queryWrapper);
                return Result.success("修改完成");
            }

            //通过list 查询是否原本在教授此课程
            LambdaQueryWrapper<CourseTeacher> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CourseTeacher::getTeacherId, teacherId);
            List<CourseTeacher> courseTeachers = courseTeacherService.getBaseMapper().selectList(queryWrapper);
            //set 1 2 3
            //item 2 4
            //清空
            QueryWrapper<CourseTeacher> teacherQueryWrapper = new QueryWrapper<>();
            teacherQueryWrapper.eq("teacher_id", teacher);
            courseTeacherService.remove(teacherQueryWrapper);
            //添加
            List<CourseTeacher> teachers = new ArrayList<>();
            Iterator<Integer> iterator = set.iterator();
            while (iterator.hasNext()) {
                Integer next = iterator.next();
                teachers.add(new CourseTeacher(next, teacher, null));
            }
            //保存
            courseTeacherService.saveBatch(teachers);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("500", e.getMessage());
        }
        return Result.success("修改完成");
    }

    @PostMapping("/teacherLogin")
    public Result teacherLogin(@RequestBody HashMap<String, String> login) {
        //获取账号
        String username = login.get("username");
        //获取密码
        String password = login.get("username");
        UserDTO userDTO = teacherService.login(username, password);
        if (StringUtils.hasLength(userDTO.getUsername())) {
            String s = TokenUtils.genToken(userDTO.getUsername(), password);
            userDTO.setToken(s);
            userDTO.setAvatarUrl("");
            userDTO.setRole("ROLE_TEACHER");
            return Result.success(userDTO);
        }
        return Result.error("500", "账号或密码错误");
    }

    @PostMapping("/upload/{teacherId}/{courseId}")
    public Result upload(@RequestParam("file") MultipartFile file, @PathVariable Integer teacherId, @PathVariable Integer courseId) {
        //查看是否存在该目录
        File file1 = new File("d:/uploadFile/" + file.getOriginalFilename());
        if (!file1.exists()) {
            file1.mkdirs();
        }
        //查询课程教师表id
        CourseTeacher one = courseTeacherService.getOne(new LambdaQueryWrapper<CourseTeacher>().eq(CourseTeacher::getTeacherId, teacherId).eq(CourseTeacher::getCourseId, courseId));
        try {
            file.transferTo(file1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        FileVo fileVo = new FileVo(null, one.getId(), file.getOriginalFilename(), file1.getPath());
        boolean save = fileService.save(fileVo);
        return Result.success(fileVo);
    }

    @GetMapping("/remove/{id}")
    public Result remove(@PathVariable Integer id) {
        //删除文件
        boolean b = fileService.removeById(id);
        if (b) {
            return Result.success();
        }
        return Result.error();
    }

    @GetMapping("/downClassWork/{classId}/{workId}")
    public void getClassStudentWork(@PathVariable String classId, @PathVariable String workId, HttpServletResponse response) throws IOException {
        Class byId = schoolClassService.getById(classId);

        //获取班级的所有学生
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getClassId, classId);
        List<Student> students = studentService.getBaseMapper().selectList(queryWrapper);
        LambdaQueryWrapper<StudentWork> studentWorkLambdaQueryWrapper = new LambdaQueryWrapper<>();
        studentWorkLambdaQueryWrapper.in(StudentWork::getStuNo, students.stream().map(Student::getId).collect(Collectors.toList()))
                .eq(StudentWork::getWorkId, workId);
        List<StudentWork> list = workService.getBaseMapper().selectList(studentWorkLambdaQueryWrapper);
        List<String> files = list.stream().map(StudentWork::getFileUrl).collect(Collectors.toList());
        OutputStream outputStream = null;
        ZipOutputStream zos = null;
        try {
            // 通过response对象获取OutputStream流
            outputStream = response.getOutputStream();
            // 设置文件ContentType类型
            response.setContentType("multipart/form-data");
            // 设置文件头
            response.setHeader("Content-Disposition", "attachment;fileName = " + URLEncoder.encode(byId.getClassName()+"班级作业.zip", "UTF-8"));
            // 获取zip的输出流
            zos = new ZipOutputStream(outputStream);
            // 循环读取文件路径集合，获取每一个文件的路径
            if (files != null) {
                for (String fp : files) {
                    File file = new File(fp);  // 通过文件路径创建文件
                    zipFile(file, zos);  // 将每一个文件写入zip文件压缩包内，即进行打包
                    // 刷新缓冲区
                    response.flushBuffer();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 压缩文件的方法
     *
     * @param inputFile
     * @param zipoutputStream
     */
    public static void zipFile(File inputFile, ZipOutputStream zipoutputStream) {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            if (inputFile.exists()) { // 判断文件是否存在
                if (inputFile.isFile()) {  // 如果是文件
                    // 创建输入流读取文件
                    fis = new FileInputStream(inputFile);
                    bis = new BufferedInputStream(fis);
                    // 将文件写入zip压缩包内
                    ZipEntry zip =
                            new ZipEntry(inputFile.getParentFile().getName() + File.separator + inputFile.getName()); //获取文件名
                    zipoutputStream.putNextEntry(zip);
                    // 进行写入文件
                    byte[] bytes = new byte[1024];
                    long fileLength = 0;
                    while (fileLength < inputFile.length()) {
                        int count = bis.read(bytes, 0, 1024);
                        fileLength += count;
                        zipoutputStream.write(bytes, 0, count);
                    }
                    // 关闭输入输出流
                    if (bis != null) {
                        bis.close();
                    }
                    if (fis != null) {
                        fis.close();
                    }
                } else {  // 如果是文件夹，则使用穷举的方法获取文件，写入zip
                    try {
                        zipoutputStream.putNextEntry(new ZipEntry(inputFile.getName() + File.separator));
                        File[] files = inputFile.listFiles();
                        for (int i = 0; i < files.length; i++) {
                            zipFile(files[i], zipoutputStream);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

